package org.jarx.android.reader;

import java.io.IOException;
import java.util.WeakHashMap;
import android.app.Activity; 
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;

public class ItemListActivity extends ListActivity {

    private static final String TAG = "ItemListActivity";
    private static final int DIALOG_MARK_AS_READ = 1;

    private final Handler handler = new Handler();
    private ReaderService service;
    private Subscription intentSub;
    private Tag intentTag;
    private boolean iconInitialized;
    private long lastItemId;
    private ItemsAdapter itemsAdapter;
    private String keyword;
    private boolean unreadOnly = true;

    private WeakHashMap<Long,String> cachedSubTitles
        = new WeakHashMap<Long,String>(10);

    private ServiceConnection serviceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder ib) {
            ReaderService.ServiceBinder b = (ReaderService.ServiceBinder) ib;
            ItemListActivity.this.service = b.getService();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            ItemListActivity.this.service = null;
        }
    };

    private BroadcastReceiver refreshReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            ItemListActivity.this.initItems(true);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Context c = getApplicationContext();

        bindService(new Intent(this, ReaderService.class), this.serviceConn,
            Context.BIND_AUTO_CREATE);

        IntentFilter filter = new IntentFilter();
        filter.addAction(ReaderService.ACTION_SYNC_SUBS_FINISHED);
        filter.addAction(ReaderService.ACTION_UNREAD_MODIFIED);
        registerReceiver(this.refreshReceiver, filter);

        setContentView(R.layout.item_list);
        ActivityHelper.bindTitle(this);

        Intent intent = getIntent();
        long subId = intent.getLongExtra(ActivityHelper.EXTRA_SUB_ID, 0);
        if (subId > 0) {
            this.intentSub = ReaderManager.getSubBy(c, Subscription._ID,
                String.valueOf(subId));
        } else {
            String tagUid = intent.getStringExtra(ActivityHelper.EXTRA_TAG_UID);
            if (tagUid != null) {
                this.intentTag = ReaderManager.getTagBy(c, Tag._UID, tagUid);
                if (this.intentTag.getType() != Tag.TYPE_FOLDER) {
                    this.unreadOnly = false;
                }
            }
        }

        initItems(false);
    }

    @Override
    public void onResume() {
        super.onResume();
        moveToLastItemPosition();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unbindService(this.serviceConn);
        unregisterReceiver(this.refreshReceiver);
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case DIALOG_MARK_AS_READ:
            return new AlertDialog.Builder(this)
                .setTitle(R.string.txt_reads)
                .setMessage(R.string.msg_confirm_mark_as_read)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        progressMarkAsRead();
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                }).create();
        }
        return null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.item_list, menu);

        MenuItem menuItem = menu.findItem(R.id.menu_sort);
        Context c = getApplicationContext();
        int type = Prefs.getItemSortType(c);
        if (type == Item.ORDER_BY_NEWER) {
            menuItem.setTitle("Sort older");
        } else {
            menuItem.setTitle("Sort newer");
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem) {
        switch (menuItem.getItemId()) {
        case R.id.menu_reload:
            progressReload();
            return true;
        case R.id.menu_unreads:
            toggleUnreadOnly(menuItem);
            return true;
        case R.id.menu_sort:
            toggleSort(menuItem);
            return true;
        case R.id.menu_mark_as_read:
            showDialog(DIALOG_MARK_AS_READ);
            return true;
        case R.id.menu_prefs:
            startActivityForResult(new Intent(this, PrefActivity.class),
                ActivityHelper.REQUEST_PREFS);
            return true;
        }
        return false;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ActivityHelper.REQUEST_ITEM_ID && data != null) {
            this.lastItemId = data.getLongExtra(ActivityHelper.EXTRA_ITEM_ID, 0);
        } else if (requestCode == ActivityHelper.REQUEST_PREFS) {
            if (Prefs.isOmitItemList(this)) {
                finish();
            }
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Long itemId = (Long) v.getTag();
        if (itemId != null) {
            this.lastItemId = itemId;
            Cursor csr = this.itemsAdapter.getCursor();
            Intent intent = new Intent(this, ItemActivity.class);
            if (this.intentSub != null) {
                intent.putExtra(ActivityHelper.EXTRA_SUB_ID,
                    this.intentSub.getId());
            } else if (this.intentTag != null) {
                intent.putExtra(ActivityHelper.EXTRA_TAG_UID,
                    this.intentTag.getUid());
            }
            intent.putExtra(ActivityHelper.EXTRA_ITEM_ID, itemId);
            intent.putExtra(ActivityHelper.EXTRA_CURSOR_POSITION,
                csr.getPosition());
            intent.putExtra(ActivityHelper.EXTRA_UNREAD_ONLY, this.unreadOnly);
            startActivityForResult(intent, ActivityHelper.REQUEST_ITEM_ID);
        }
    }

    private void progressReload() {
        if (this.service == null) {
            return;
        }
        final ReaderManager rman = this.service.getSharedReaderManager();
        if (rman == null) {
            return;
        }
        final Context c = getApplicationContext();
        final Subscription sub = this.intentSub;
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setIndeterminate(true);
        dialog.setMessage(getText(R.string.msg_sync_running));
        dialog.show();
        new Thread() {
            public void run() {
                try {
                    if (sub != null) {
                        long syncTime = System.currentTimeMillis();
                        rman.syncItems(sub, syncTime, true);
                    } else {
                        rman.sync();
                    }
                } catch (IOException e) {
                    ActivityHelper.showToast(c, e);
                } catch (ReaderException e) {
                    ActivityHelper.showToast(c, e);
                }
                handler.post(new Runnable() {
                    public void run() {
                        ItemListActivity.this.initItems(true);
                        dialog.dismiss();
                    }
                });
            }
        }.start();
    }

    private void toggleUnreadOnly(MenuItem menuItem) {
        this.unreadOnly = !this.unreadOnly;
        initListAdapter();
        if (this.unreadOnly) {
            menuItem.setTitle("Show reads");
        } else {
            menuItem.setTitle("Hide reads");
        }
    }

    private void toggleSort(MenuItem menuItem) {
        Context c = getApplicationContext();
        int type = Prefs.getItemSortType(c);
        if (type == Item.ORDER_BY_NEWER) {
            Prefs.setItemSortType(c, Item.ORDER_BY_OLDER);
            menuItem.setTitle("Sort newer");
        } else {
            Prefs.setItemSortType(c, Item.ORDER_BY_NEWER);
            menuItem.setTitle("Sort older");
        }
        initListAdapter();
    }

    private void progressMarkAsRead() {
        if (this.service == null) {
            return;
        }
        final ReaderManager rman = this.service.getSharedReaderManager();
        if (rman == null) {
            return;
        }
        final Context c = getApplicationContext();
        final Subscription sub = this.intentSub;
        final Tag tag = this.intentTag;
        final long time = System.currentTimeMillis();
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setIndeterminate(true);
        dialog.setMessage(getText(R.string.msg_mark_as_read_running));
        dialog.show();
        new Thread() {
            public void run() {
                try {
                    if (sub != null) {
                        rman.syncMarkAllAsRead(sub, time);
                    } else if (tag != null) {
                        rman.syncMarkAllAsRead(tag, time);
                    } else {
                        rman.syncMarkAllAsRead(time);
                    }
                } catch (IOException e) {
                    ActivityHelper.showToast(c, e);
                } catch (ReaderException e) {
                    ActivityHelper.showToast(c, e);
                }
                handler.post(new Runnable() {
                    public void run() {
                        ItemListActivity.this.initItems(true);
                        dialog.dismiss();
                    }
                });
            }
        }.start();
    }

    public void initItems(boolean reloadSubTab) {
        bindSubTitleView(reloadSubTab);
        initListAdapter();
    }

    private void initListAdapter() {
        Query q = ActivityHelper.getItemQuery(this.intentSub, this.intentTag,
            this.unreadOnly);
        q.setSelection(Item.PREFIX_SELECT_NO_CONTENT);
        Cursor csr = new Item.FilterCursor(q.managedQuery(this));
        int count = csr.getCount();
        if (count == 0) {
            TextView emptyView = (TextView) findViewById(android.R.id.empty);
            if (this.unreadOnly) {
                emptyView.setText(getText(R.string.msg_no_item_unread));
            } else {
                emptyView.setText(getText(R.string.msg_no_item));
            }
        }
        if (this.itemsAdapter == null) {
            this.itemsAdapter = new ItemsAdapter(this, csr);
            setListAdapter(this.itemsAdapter);
        } else {
            this.itemsAdapter.changeCursor(csr);
        }
    }

    private void moveToLastItemPosition() {
        if (this.lastItemId <= 0 || this.itemsAdapter == null) {
            return;
        }
        Item.FilterCursor csr = (Item.FilterCursor) this.itemsAdapter.getCursor();
        ActivityHelper.moveToItemId(csr, this.lastItemId);
        int pos = csr.getPosition();
        getListView().setSelectionFromTop(pos, 48);
    }

    private void bindSubTitleView(boolean reloadSubTab) {
        Context c = getApplicationContext();
        if (reloadSubTab) {
            if (this.intentSub != null) {
                this.intentSub = ReaderManager.getSubBy(c, Subscription._ID,
                    String.valueOf(this.intentSub.getId()));
            } else if (this.intentTag != null) {
                this.intentTag = ReaderManager.getTagBy(c, Tag._UID,
                    this.intentTag.getUid());
            }
        }
        TextView subTitleView = (TextView) findViewById(R.id.sub_title);
        ImageView iconView = (ImageView) findViewById(R.id.sub_icon);
        if (this.intentSub != null) {
            Subscription sub = this.intentSub;
            subTitleView.setText(ActivityHelper.toLabelWithUnread(sub));
            if (!this.iconInitialized) {
                Bitmap icon = sub.getIcon(this);
                if (icon == null) {
                    iconView.setImageResource(R.drawable.item_read);
                } else {
                    iconView.setImageBitmap(icon);
                }
                this.iconInitialized = true;
            }
        } else if (this.intentTag != null) {
            Tag tag = this.intentTag;
            subTitleView.setText(ActivityHelper.toLabelWithUnread(tag, this));
            switch (tag.getType()) {
            case Tag.TYPE_TAG_STARRED:
                if (!this.iconInitialized) {
                    iconView.setImageResource(R.drawable.star);
                    this.iconInitialized = true;
                }
                break;
            case Tag.TYPE_TAG_LABEL:
                if (!this.iconInitialized) {
                    iconView.setImageResource(R.drawable.tag);
                    this.iconInitialized = true;
                }
                break;
            case Tag.TYPE_FOLDER:
                if (!this.iconInitialized) {
                    iconView.setImageResource(R.drawable.folder_open);
                    this.iconInitialized = true;
                }
                break;
            }
        } else {
            subTitleView.setText(ActivityHelper.toLabelWithUnread(
                getText(R.string.txt_all), Prefs.getUnreadCount(c)));
        }
    }

    private String getCachedSubTitle(long subId) {
        String title = this.cachedSubTitles.get(subId);
        if (title == null && this.service != null) {
            ReaderManager rman = this.service.getSharedReaderManager();
            title = rman.getSubTitleById(subId);
            this.cachedSubTitles.put(subId, title);
        }
        return (title == null) ? "": title;
    }

    private class ItemsAdapter extends ResourceCursorAdapter {

        private ItemsAdapter(Context c, Cursor csr) {
            super(c, R.layout.item_list_row, csr, false);
        }

        @Override
        public void bindView(View v, Context c, Cursor csr) {
            Item.FilterCursor itemCsr = (Item.FilterCursor) csr;

            ImageView iconView = (ImageView) v.findViewById(R.id.icon_read_unread);
            TextView titleView = (TextView) v.findViewById(R.id.title);
            TextView summaryView = (TextView) v.findViewById(R.id.summary);

            Item item = itemCsr.getItem();
            iconView.setImageResource(item.isRead()
                ? R.drawable.item_read: R.drawable.item_unread);
            titleView.setText(item.getTitle());
            StringBuilder summary = new StringBuilder(64);
            summary.append(Utils.formatTimeAgo(item.getPublishedTime()));
            if (ItemListActivity.this.intentSub == null) {
                summary.append("  ");
                summary.append(getCachedSubTitle(item.getSubId()));
            }
            summaryView.setText(summary);

            v.setTag(item.getId());
        }

        @Override
        public void onContentChanged() {
            super.onContentChanged();
            ItemListActivity.this.bindSubTitleView(true);
        }
    }
}
